package cn.thornbird.orgsync.service.impl;

import cn.thornbird.orgsync.entity.BaseEntity;
import cn.thornbird.orgsync.exception.BadRequestException;
import cn.thornbird.orgsync.exception.NotFoundException;
import cn.thornbird.orgsync.repository.BaseRepository;
import cn.thornbird.orgsync.util.ReflectUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

@Slf4j
public class BaseService<R extends BaseRepository<E>, E extends BaseEntity> {

    public static final String REFERENCING_CURRENT_RECORD = "当前记录被引用";

    protected E findFirstById(R repository, String id) throws NotFoundException {
        Assert.notNull(id, "ID不能为空");
        E entity = repository.findFirstById(id);
        if (entity == null) {
            throw new NotFoundException();
        }
        return entity;
    }

    protected void checkDuplicate(R repository, String id, String fieldName, String fieldValue)
            throws BadRequestException {
        if (StringUtils.isEmpty(fieldValue)) {
            return;
        }
        Object record = getRecord(repository, fieldName, fieldValue);
        if (id == null) {
            if (record != null) {
                throw new BadRequestException(String.format("字段值重复: %s", fieldName));
            }
        } else {
            if (record != null) {
                String currentId = (String) ReflectUtil.getValue(record, "id");
                if (currentId != null && !currentId.equals(id)) {
                    throw new BadRequestException(String.format("字段值重复: %s", fieldName));
                }
            }
        }
    }

    private Object getRecord(R repository, String fieldName, String fieldValue) {
        Object record = null;
        String methodName = "findFirstBy" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
        try {
            Method method = ReflectUtil.getMethod(repository, methodName);
            if (method == null) {
                method = ReflectUtil.getMethod(repository, methodName + "IgnoreCase");
            }
            if (method != null) {
                method.setAccessible(true);
                record = method.invoke(repository, fieldValue);
            }
        } catch (InvocationTargetException | IllegalAccessException e) {
            log.error("error", e);
        }
        return record;
    }

}
